import 'dart:collection';
import 'dart:convert';
import 'dart:typed_data';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:flutter_hi_cache/flutter_hi_cache.dart';
import 'package:get/get.dart' hide Response;
import 'package:yysk_app/env/env.dart';
import 'package:yysk_app/model/base/json_convert_content.dart';
import 'package:yysk_app/net/interceptor/error_interceptor.dart';
import 'package:yysk_app/net/response_data.dart';
import 'package:yysk_app/pages/login/login_controller.dart';
import 'package:yysk_app/pages/login/login_page.dart';
import 'package:yysk_app/routes/global_controller.dart';
import 'package:yysk_app/utils/dialog_widget.dart';
import 'package:yysk_app/utils/encrypt.dart';
import 'package:yysk_app/utils/get_sign.dart';
import 'package:yysk_app/utils/helper.dart';
import 'package:yysk_app/utils/js_tool.dart';
import 'package:yysk_app/utils/log_util.dart';
import 'package:lottie/lottie.dart';
import 'package:oktoast/oktoast.dart';
import 'package:uuid/uuid.dart';

enum Method { get, post, put, delete, patch }

class HttpManager {
  static final _instance = HttpManager._internal();

  final Dio _dio = Dio();

  factory HttpManager() => _instance;

  HttpManager._internal() {
    _dio.interceptors.add(ErrorInterceptors());
  }

  Future<ResponseData<T>?> netFetch<T>(
    url, {
    params,
    Function(ResponseData<T> r)? success,
    Function(int code, String message)? fail,
    Method method = Method.post,
    Map<String, dynamic>? header,
    Options? options,
    noTip = false,
    uploadFailUnEncryption = true, //上传文件不加密
  }) async {
    // consoleLog('$params==原生的数据');
    var sendParams = CryptoUtils.encryptAndBase64Encode(
      encryptkey.baseUrl,
      jsonEncode(params),
    );
    var env = Env.envConfig;
    var uuid = Uuid();

    fail =
        fail ??
        (code, message) {
          consoleLog(message);
        };

    Map<String, dynamic> headers = HashMap();
    headers['Content-Type'] = 'application/json';

    if (env.envEncryption && uploadFailUnEncryption) {
      headers['X-Algorithm-Version'] = 'v1'; // 24年加密逻辑，服务端根据此字段识别是否触发加密
    }
    var sign = getSign();
    final requestTime = DateTime.now().millisecondsSinceEpoch.toString();
    //支付接口相关需要加请求头  options.headers['x-pay-token'] = token;
    if (url.contains('/pay/')) {
      headers['x-pay-token'] =
          await HiCache.getInstance().get(GlobalController.xPayToken) ?? '';
    }
    if (url.contains('/common/common/')) {
      var uniqueId = HiCache.getInstance().get(GlobalController.uuid);
      if (uniqueId == '' || uniqueId == null) {
        uniqueId = uuid.v4();
        HiCache.getInstance().setString('uuid', uniqueId);
      }
      headers['uuid'] = uniqueId;
    }
    headers['requestTime'] = requestTime;
    headers['timestamp'] = sign['timestamp'];
    headers['sign'] = sign['sign'];
    headers['nonce'] = sign['nonce'];

    if (header != null) {
      headers.addAll(header);
    }

    if (options != null) {
      options.headers = headers;
      options.method = method.name;
    } else {
      options = Options(method: method.name);
      options.headers = headers;
    }
    //timeout 2秒  ,那就给5秒时间请求
    // options.sendTimeout =  Duration(seconds: 2);
    options.receiveTimeout = Duration(seconds: 10);
    try {
      if (url.contains('/boxOrder/queryAward')) {
      } else {
        EasyLoading.show(
          indicator: Lottie.asset(
            'static/json/kongfu.json',
            width: 40.px,
            height: 40.px,
          ),
          dismissOnTap: false,
        );
      }

      debugPrint('请求参数${params.toString()}');
      Response response = await _dio.request(
        url,
        data:
            (env.envEncryption &&
                    !url.contains('mall/buyer') &&
                    uploadFailUnEncryption)
                ? {'data': sendParams}
                : params,
        options: options,
      );
      debugPrint('未格式化$url,${response.data}');
      JsonConvertClassCollection convertFunctMap = JsonConvertClassCollection();
      var key = T.toString();
      var covertFunc =
          convertFunctMap.containsKey(key)
              ? convertFunctMap[key]! as T Function(Map<String, dynamic>)
              : (json) => json as T;
      String res;
      ResponseData<T> result;
      if (env.envEncryption &&
          !url.contains('mall/buyer') &&
          uploadFailUnEncryption) {
        res = CryptoUtils.base64DecodeAndDecrypt(
          encryptkey.baseUrl,
          '${response.data['data']}',
        );
        result = ResponseData.fromJson(
          CryptoUtils.safeJsonParse(res),
          covertFunc,
        );
      } else {
        result = ResponseData.fromJson(response.data, covertFunc);
      }
      if (result.successful == true || result.code == 200) {
        success?.call(result);
      } else {
        if (url.contains('/boxOrder/queryAward') && result.code == 80009) {
          // 心愿盒跳转中台订单支付状态不做提示
        } else if (url.contains('promotion/coupon/activity')) {
          // 商城登录后自动调用 获取优惠券接口 失败不做提示
        } else {
          _onError(
            result.code,
            result.message ?? '',
            fail,
            params,
            url,
            noTip: noTip,
          );
        }
      }
      EasyLoading.dismiss();
      return result;
    } on DioException catch (e) {
      EasyLoading.dismiss();
      consoleLog("http DioException: $e");

      _cancelLogPrint(e, url);
      _onError(12345, '系统异常', fail, params, url);
      return null;
    } finally {
      EasyLoading.dismiss();
    }
  }

  void _onError(
    int? code,
    String msg,
    Function(int code, String msg)? onError,
    Map<dynamic, dynamic>? params,
    String? url, {
    bool? noTip,
  }) {
    Log.e('接口名称： $url');
    Log.json('请求参数: $params');
    Log.e('接口请求异常: code: $code, msg: $msg');
    //冻结
    if (code == 140005) {
      dismissAllToast();
      showToast('$msg');
      HiCache.getInstance().remove(LoginController.boardingPassToken);
      // Get.offAllNamed(LoginPage.path);
      return;
    }
    if (code == 401) {
      dismissAllToast();
      showToast('登录已失效，请重新登录');
      HiCache.getInstance().remove(LoginController.boardingPassToken);
      Get.offAllNamed(LoginPage.path);
      // showConfirmDialog(
      //   context: Get.context!,
      //   fontSize: 16,
      //   closeButton: false,
      //   message: '登录已失效，请重新登录',
      //   type: 'login_expired',
      //   actions: [
      //     ActionModel(
      //       width: 204,
      //       label: '我知道了',
      //       onPressed: () {
      //         dismissAllToast();
      //         // showToast('登录已过期');
      //         HiCache.getInstance().remove(LoginController.boardingPassToken);
      //         Get.offAllNamed(LoginPage.path);
      //       },
      //     ),
      //   ],
      // );
      return;
    }
    if (code == null) {
      code = 12345;
      msg = '未知异常';
    }
    if (code == 12345) {
      code = 12345;
      msg = '未知异常';
    }
    if (noTip == false) {
      showToast(msg.toString());
    }
    onError?.call(code, msg);
  }

  void _cancelLogPrint(dynamic e, String url) {
    if (e is DioException && CancelToken.isCancel(e)) {
      Log.e('接口请求取消: $url');
    }
  }

  put(
    Uri parse, {
    required Uint8List body,
    required Map<String, dynamic> headers,
  }) {}
}

final HttpManager http = HttpManager();
